from datetime import datetime
from typing import Dict, Any
from uuid import UUID
from fastapi import APIRouter, HTTPException, status, Depends, Request
from fastapi.responses import JSONResponse
from src.models.schemas.auth import (
    UserCreate,
    UserLogin,
    UserResponse,
    LoginResponse,
    StandardResponse,
    PasswordResetRequest,
    PasswordResetConfirm,
    TokenResponse
)
from src.core.security import get_current_user, verify_token
from src.services.auth import AuthService
from src.core.dependencies import get_auth_service
import logging

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/auth", tags=["Authentication"])


@router.post("/register", response_model=StandardResponse, status_code=status.HTTP_201_CREATED)
async def register(
    user_data: UserCreate,
    auth_service: AuthService = Depends(get_auth_service)
) -> Dict[str, Any]:
    """Register a new user."""
    try:
        user, token = await auth_service.register_user(user_data)
        
        if not user:
            return JSONResponse(
                status_code=status.HTTP_400_BAD_REQUEST,
                content={
                    "success": False,
                    "error": {
                        "code": "AUTH_001",
                        "message": token or "Registration failed",
                        "details": {},
                        "timestamp": datetime.utcnow().isoformat(),
                        "requestId": str(UUID())
                    }
                }
            )
        
        user_response = UserResponse.model_validate(user)
        
        return {
            "success": True,
            "data": {
                "user": user_response.model_dump(),
                "token": token
            },
            "message": "User registered successfully",
            "timestamp": datetime.utcnow()
        }
    except Exception as e:
        logger.error(f"Registration error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Registration failed"
        )


@router.post("/login", response_model=StandardResponse)
async def login(
    login_data: UserLogin,
    auth_service: AuthService = Depends(get_auth_service)
) -> Dict[str, Any]:
    """Login user and return JWT token."""
    try:
        user, token = await auth_service.login_user(login_data)
        
        if not user:
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "success": False,
                    "error": {
                        "code": "AUTH_001",
                        "message": token or "Authentication failed",
                        "details": {},
                        "timestamp": datetime.utcnow().isoformat(),
                        "requestId": str(UUID())
                    }
                }
            )
        
        user_response = UserResponse.model_validate(user)
        
        return {
            "success": True,
            "data": {
                "user": user_response.model_dump(),
                "token": token
            },
            "message": "Login successful",
            "timestamp": datetime.utcnow()
        }
    except Exception as e:
        logger.error(f"Login error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Login failed"
        )


@router.post("/refresh", response_model=StandardResponse)
async def refresh_token(
    current_user: Dict[str, Any] = Depends(get_current_user),
    auth_service: AuthService = Depends(get_auth_service)
) -> Dict[str, Any]:
    """Refresh JWT token."""
    try:
        user_id = current_user.get("user_id")
        
        # Get current token from request
        # In production, this would be extracted from the Authorization header
        old_token = ""  # This would be extracted from the request
        
        new_token = await auth_service.refresh_token(user_id, old_token)
        
        if not new_token:
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "success": False,
                    "error": {
                        "code": "AUTH_001",
                        "message": "Failed to refresh token",
                        "details": {},
                        "timestamp": datetime.utcnow().isoformat(),
                        "requestId": str(UUID())
                    }
                }
            )
        
        return {
            "success": True,
            "data": {
                "token": new_token
            },
            "message": "Token refreshed successfully",
            "timestamp": datetime.utcnow()
        }
    except Exception as e:
        logger.error(f"Token refresh error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Token refresh failed"
        )


@router.post("/logout", response_model=StandardResponse)
async def logout(
    current_user: Dict[str, Any] = Depends(get_current_user),
    auth_service: AuthService = Depends(get_auth_service)
) -> Dict[str, Any]:
    """Logout user."""
    try:
        user_id = current_user.get("user_id")
        await auth_service.logout_user(user_id)
        
        return {
            "success": True,
            "data": None,
            "message": "Logout successful",
            "timestamp": datetime.utcnow()
        }
    except Exception as e:
        logger.error(f"Logout error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Logout failed"
        )


@router.post("/forgot-password", response_model=StandardResponse)
async def forgot_password(
    request_data: PasswordResetRequest,
    auth_service: AuthService = Depends(get_auth_service)
) -> Dict[str, Any]:
    """Request password reset."""
    try:
        success, token = await auth_service.request_password_reset(request_data.email)
        
        # In production, don't include the token in response - send via email
        # For development, we're including it in the response
        response_data = {}
        if token and settings.DEBUG:  # Only include token in debug mode
            response_data["reset_token"] = token
        
        return {
            "success": True,
            "data": response_data,
            "message": "If the email exists, a password reset link has been sent",
            "timestamp": datetime.utcnow()
        }
    except Exception as e:
        logger.error(f"Password reset request error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Password reset request failed"
        )


@router.post("/reset-password", response_model=StandardResponse)
async def reset_password(
    reset_data: PasswordResetConfirm,
    auth_service: AuthService = Depends(get_auth_service)
) -> Dict[str, Any]:
    """Reset password with valid token."""
    try:
        success, message = await auth_service.reset_password(
            reset_data.email,
            reset_data.token,
            reset_data.new_password
        )
        
        if not success:
            return JSONResponse(
                status_code=status.HTTP_400_BAD_REQUEST,
                content={
                    "success": False,
                    "error": {
                        "code": "AUTH_001",
                        "message": message,
                        "details": {},
                        "timestamp": datetime.utcnow().isoformat(),
                        "requestId": str(UUID())
                    }
                }
            )
        
        return {
            "success": True,
            "data": None,
            "message": message,
            "timestamp": datetime.utcnow()
        }
    except Exception as e:
        logger.error(f"Password reset error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Password reset failed"
        )


@router.get("/me", response_model=StandardResponse)
async def get_current_user_info(
    current_user: Dict[str, Any] = Depends(get_current_user),
    auth_service: AuthService = Depends(get_auth_service)
) -> Dict[str, Any]:
    """Get current user information."""
    try:
        user_id = UUID(current_user.get("user_id"))
        user = await auth_service.get_user_by_id(user_id)
        
        if not user:
            return JSONResponse(
                status_code=status.HTTP_404_NOT_FOUND,
                content={
                    "success": False,
                    "error": {
                        "code": "AUTH_001",
                        "message": "User not found",
                        "details": {},
                        "timestamp": datetime.utcnow().isoformat(),
                        "requestId": str(UUID())
                    }
                }
            )
        
        user_response = UserResponse.model_validate(user)
        
        return {
            "success": True,
            "data": {
                "user": user_response.model_dump()
            },
            "message": "User information retrieved successfully",
            "timestamp": datetime.utcnow()
        }
    except Exception as e:
        logger.error(f"Get user error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get user information"
        )


from src.core.config import settings